package cn.iocoder.yudao.module.shop.service.member;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.module.agent.dal.dataobject.user.AgentUserDO;
import cn.iocoder.yudao.module.agent.service.user.AgentUserService;
import cn.iocoder.yudao.module.blog.dal.dataobject.jiutag.BlogJiuTagDO;
import cn.iocoder.yudao.module.blog.service.jiutag.BlogJiuTagService;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserRespVO;
import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO;
import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
import cn.iocoder.yudao.module.member.service.group.MemberGroupService;
import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
import cn.iocoder.yudao.module.member.service.tag.MemberTagService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
import cn.iocoder.yudao.module.shop.controller.admin.item.vo.ShopItemRespVO;
import cn.iocoder.yudao.module.shop.controller.admin.member.vo.*;
import cn.iocoder.yudao.module.shop.controller.admin.memberpay.vo.ShopMemberPayItemUpdateReqVO;
import cn.iocoder.yudao.module.shop.controller.admin.order.vo.ShopOrderPageReqVO;
import cn.iocoder.yudao.module.shop.controller.admin.order.vo.ShopOrderRespVO;
import cn.iocoder.yudao.module.shop.convert.member.ShopMemberUserConvert;
import cn.iocoder.yudao.module.shop.convert.order.ShopOrderConvert;
import cn.iocoder.yudao.module.shop.dal.dataobject.crosstenant.ShopCrossTenantDO;
import cn.iocoder.yudao.module.shop.dal.dataobject.memberhealth.ShopMemberHealthDO;
import cn.iocoder.yudao.module.shop.dal.dataobject.memberpay.ShopMemberPayItemDO;
import cn.iocoder.yudao.module.shop.dal.dataobject.order.ShopOrderDO;
import cn.iocoder.yudao.module.shop.dal.dataobject.order.ShopOrderItemDO;
import cn.iocoder.yudao.module.shop.dal.dataobject.price.ShopPriceDO;
import cn.iocoder.yudao.module.shop.service.crosstenant.ShopCrossTenantService;
import cn.iocoder.yudao.module.shop.service.item.ShopItemService;
import cn.iocoder.yudao.module.shop.service.itemtimesrecharge.ShopItemTimesRechargeService;
import cn.iocoder.yudao.module.shop.service.memberhealth.ShopMemberHealthService;
import cn.iocoder.yudao.module.shop.service.memberpay.ShopMemberPayItemService;
import cn.iocoder.yudao.module.shop.service.order.ShopOrderItemService;
import cn.iocoder.yudao.module.shop.service.order.ShopOrderService;
import cn.iocoder.yudao.module.shop.service.price.ShopPriceService;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenantdetail.TenantDetailDO;
import cn.iocoder.yudao.module.system.service.tenantdetail.TenantDetailService;
import com.alibaba.druid.support.clickhouse.BalancedClickhouseDriver;
import jodd.util.StringUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;

import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.shop.enums.ErrorCodeConstants.*;

@Service
@Validated
public class ShopMemberServiceImpl implements ShopMemberService{

    @Resource
    private MemberUserService memberUserService;

    @Resource
    private MemberUserMapper memberUserMapper;

    @Resource
    private AdminUserApi adminUserApi;

    @Resource
    private MemberUserApi memberUserApi;

    @Resource
    private MemberTagService memberTagService;
    @Resource
    private MemberLevelService memberLevelService;
    @Resource
    private MemberGroupService memberGroupService;

    @Resource
    private PayWalletService payWalletService;

    @Resource
    private AgentUserService agentUserService;

    @Resource
    private ShopMemberPayItemService shopMemberPayItemService;

    @Resource
    private ShopMemberPayItemService memberPayItemService;

    @Resource
    private ShopPriceService shopPriceService;

    @Resource
    private ShopMemberHealthService shopMemberHealthService;

    @Resource
    private ShopOrderService shopOrderService;

    @Resource
    private ShopOrderItemService shopOrderItemService;

    @Resource
    private ShopItemService shopItemService;

    @Resource
    private BlogJiuTagService jiuTagService;

    @Resource
    private ShopItemTimesRechargeService shopItemTimesRechargeService;

    @Resource
    private TenantDetailService tenantDetailService;

    @Resource
    private ShopCrossTenantService shopCrossTenantService;


    @Override
    public PageResult<MemberUserDetailRespVO> getUserPage(MemberUserPageReqVO pageVO){
        PageResult<MemberUserDO> pageResult = memberUserService.getUserPage(pageVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return PageResult.empty();
        }

        Collection<Long> userIds = convertSet(pageResult.getList(), MemberUserDO::getId);

        // 处理用户标签返显
        Set<Long> tagIds = pageResult.getList().stream()
                .map(MemberUserDO::getTagIds)
                .filter(Objects::nonNull)
                .flatMap(Collection::stream)
                .collect(Collectors.toSet());
        List<MemberTagDO> tags = memberTagService.getTagList(tagIds);
        // 处理用户级别返显
        List<MemberLevelDO> levels = memberLevelService.getLevelList(
                convertSet(pageResult.getList(), MemberUserDO::getLevelId));
        // 处理用户分组返显
        List<MemberGroupDO> groups = memberGroupService.getGroupList(
                convertSet(pageResult.getList(), MemberUserDO::getGroupId));

        // 用户页数据
        PageResult<MemberUserRespVO> userPage = MemberUserConvert.INSTANCE.convertPage(pageResult, tags, levels, groups);

        // 钱包数据
        List<PayWalletDO> wallets = payWalletService.getOrCreateWallet(userIds, UserTypeEnum.MEMBER.getValue());

        // 价格数据
        List<ShopMemberPayItemDO> memberpayItems = shopMemberPayItemService.getMemberPayItemByMemberId(userIds);

        Set<Long> pricePackageIdList = convertSet(memberpayItems, ShopMemberPayItemDO::getPriceId);

        List<ShopPriceDO> shopPriceDOList = shopPriceService.getPriceList(pricePackageIdList);

        return ShopMemberUserConvert.INSTANCE.convertPage(userPage, wallets, memberpayItems, shopPriceDOList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createMember(MemberUserCreateReqVO createReqVO){
        MemberUserDO memberUserDO = memberUserService.getUserByMobile(createReqVO.getMobile());
        if(memberUserDO != null){
            throw exception(MEMBER_HAS_REGISTER);
        }

        memberUserDO = memberUserService.createUserIfAbsent(createReqVO.getMobile(), "127.0.0.1", null, createReqVO.getTenantId());

        LoginUser loginUser = getLoginUser();
        if(loginUser == null) {
            throw exception(MEMBER_CREATE_ERROR);
        }

        memberUserDO.setTenantId(loginUser.getTenantId());
        memberUserDO.setSex(createReqVO.getSex());
        memberUserDO.setMark(createReqVO.getMark());
        memberUserDO.setNickname(createReqVO.getNickname());
        memberUserDO.setName(createReqVO.getNickname());
        memberUserDO.setBirthday(createReqVO.getBirthday());
        memberUserDO.setTenantId(createReqVO.getTenantId());

        memberUserMapper.updateById(memberUserDO);

        memberPayItemService.createMemberPayItem(createReqVO.getPriceId(), memberUserDO.getId());

        AdminUserRespDTO adminUserRespDTO = adminUserApi.getUser(loginUser.getId());
        MemberUserRespDTO memberUserRespDTO = memberUserApi.getUserByMobile(adminUserRespDTO.getMobile());
        // 如果对应User账号，没有member 账号 不管代理， 因为代理都是有member的
        if(memberUserRespDTO != null){
            // todo 可能用店员账号登录
            // 如果店主是代理，绑定会员
            AgentUserDO agentUserDO = agentUserService.getByUserId(memberUserRespDTO.getId());
            if(agentUserDO != null){
                agentUserService.bindBrokerageUserByUserId(agentUserDO.getUserId(), memberUserDO.getId());
            }
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean quickCreateMember(MemberUserCreateReqVO createReqVO){
        Long count = memberUserService.getUserCountByNickname(createReqVO.getNickname());
        if(count > 0){
            throw exception(MEMBER_HAS_NICKNAME);
        }

        MemberUserDO memberUserDO = memberUserService.quickCreateUserByNickname(createReqVO.getNickname(), "127.0.0.1", null, createReqVO.getTenantId());
        LoginUser loginUser = getLoginUser();
        if(loginUser == null) {
            throw exception(MEMBER_CREATE_ERROR);
        }

        memberUserDO.setTenantId(loginUser.getTenantId());
        memberUserDO.setSex(createReqVO.getSex());
        memberUserDO.setMark(createReqVO.getMark());
        memberUserDO.setNickname(createReqVO.getNickname());
        memberUserDO.setName(createReqVO.getNickname());
        memberUserDO.setBirthday(createReqVO.getBirthday());
        memberUserDO.setTenantId(createReqVO.getTenantId());

        memberUserMapper.updateById(memberUserDO);

        memberPayItemService.createMemberPayItem(createReqVO.getPriceId(), memberUserDO.getId());

        AdminUserRespDTO adminUserRespDTO = adminUserApi.getUser(loginUser.getId());
        MemberUserRespDTO memberUserRespDTO = memberUserApi.getUserByMobile(adminUserRespDTO.getMobile());
        // 如果对应User账号，没有member 账号 不管代理， 因为代理都是有member的
        if(memberUserRespDTO != null){
            // todo 可能用店员账号登录
            // 如果店主是代理，绑定会员
            AgentUserDO agentUserDO = agentUserService.getByUserId(memberUserRespDTO.getId());
            if(agentUserDO != null){
                agentUserService.bindBrokerageUserByUserId(agentUserDO.getUserId(), memberUserDO.getId());
            }
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateMember(MemberUserUpdateReqVO updateReqVO){
        MemberUserDO memberUserDO = memberUserService.getUser(updateReqVO.getId());
        if(memberUserDO == null){
            throw exception(MEMBER_NOT_EXISTS);
        }

        MemberUserDO updateObj = ShopMemberUserConvert.INSTANCE.convert(updateReqVO);
        memberUserMapper.updateById(updateObj);

        ShopMemberPayItemDO payItemDO = memberPayItemService.getMemberPayItemByMemberId(memberUserDO.getId());
        ShopMemberPayItemUpdateReqVO payItemUpdateReqVO = new ShopMemberPayItemUpdateReqVO();
        payItemUpdateReqVO.setPriceId(updateReqVO.getPriceId());
        payItemUpdateReqVO.setId(payItemDO.getId());
        payItemUpdateReqVO.setMemberId(memberUserDO.getId());

        memberPayItemService.updpateMemberPayItem(payItemUpdateReqVO);

        return true;
    }

    @Override
    public Boolean timesRecharge(TimesRechargeCreateReqVO reqVO){
        shopItemTimesRechargeService.timesRecharge(reqVO.getMemberId(), reqVO.getItemId(), reqVO.getPayPrice(), reqVO.getTimes(), "会员充值", reqVO.getTenantId());

        return true;
    }

    @Override
    public ShopMemberDetailRespVO getMemberDetail(Long memberId, Integer orderCount){
        //1 会员信息
        MemberUserDO memberUserDO = memberUserService.getUser(memberId);

        //2 钱包信息
        PayWalletDO walletDO = payWalletService.getWallet(memberId, UserTypeEnum.MEMBER.getValue());
        Integer balance = 0;
        Integer totalRecharge = 0;
        if(walletDO != null){
            balance = walletDO.getBalance();
            totalRecharge = walletDO.getTotalRecharge();
        }

        //3 健康档案
        ShopMemberHealthDO shopMemberHealthDO = shopMemberHealthService.getMemberHealthByUserId(memberId);
        List<BlogJiuTagDO> tagList = new ArrayList<>();
        if(shopMemberHealthDO != null){
            //3.1标签实例
            Set<Long> tagIds = new HashSet<>();
            if(shopMemberHealthDO.getTags() != null && StringUtil.isNotEmpty(shopMemberHealthDO.getTags())){
                String[] ids = shopMemberHealthDO.getTags().split(";");
                for(int i = 0; i<ids.length ; i++){
                    tagIds.add(Long.parseLong(ids[i]));
                }
            }
            tagList = jiuTagService.getJiuTagList(tagIds);
        }

        //4 最近店铺订单
        ShopOrderPageReqVO shopOrderPageReqVO = new ShopOrderPageReqVO();
        shopOrderPageReqVO.setPageSize(orderCount);
        shopOrderPageReqVO.setPageNo(1);
        shopOrderPageReqVO.setMemberId(memberId);
        shopOrderPageReqVO.setPayStatus(true);
        PageResult<ShopOrderDO> pageResult = shopOrderService.getOrderPage(shopOrderPageReqVO);

        //4.1 查询艾灸师
        Set<Long> userIds = convertSet(pageResult.getList(), ShopOrderDO::getUserId);
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);

        //4.2 查询用户信息
        Set<Long> memberIds = new HashSet<>();
        memberIds.add(memberId);
        Map<Long, MemberUserRespDTO> memberMap = memberUserApi.getUserMap(memberIds);

        //4.3查询店内项目
        List<ShopOrderItemDO> shopOrderItemDOS = shopOrderItemService.getShopOrderItemListByOrderId(convertSet(pageResult.getList(), ShopOrderDO::getId));
        Set<Long> itemIds = convertSet(shopOrderItemDOS, ShopOrderItemDO::getOptItemId);
        Map<Long, ShopItemRespVO> shopItemRespVOMap = shopItemService.getItemMap(itemIds);

        List<ShopOrderRespVO> orderList = ShopOrderConvert.INSTANCE.convertList(pageResult.getList(), shopOrderItemDOS, shopItemRespVOMap, memberMap, userMap);

        return ShopMemberUserConvert.INSTANCE.convertDetail(memberUserDO, balance, totalRecharge, shopMemberHealthDO, tagList, orderList);
    }

    @Override
    public List<ShopMemberSearchRespVO> searchMember(MemberUserSearchReqVO reqVO){
        // cross tenantId
        List<Long> tenantIds = new ArrayList<>();
        tenantIds.add(reqVO.getTenantId());

        List<ShopCrossTenantDO> crossTenantDOList = shopCrossTenantService.getCrossTenantList(reqVO.getTenantId());
        for(int i = 0; i<crossTenantDOList.size(); i++){
            tenantIds.add(crossTenantDOList.get(i).getCrossTenantId());
        }

        List<MemberUserDO> memberUserDOList = memberUserService.searchUser(reqVO.getMobile(), reqVO.getNickname(), tenantIds);
        List<TenantDetailDO> tenantDetailDOList = tenantDetailService.getTenantDetailListByTenantIds(tenantIds);

        return ShopMemberUserConvert.INSTANCE.convertSearchMember(memberUserDOList, tenantDetailDOList);
    }
}
